package com.zsxb.crm.service.impl;

import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;

import com.zsxb.crm.constant.RedisConstant;
import com.zsxb.crm.context.StatusContext;
import com.zsxb.crm.dto.LoginDTO;
import com.zsxb.crm.enumeration.ResultCodeEnum;
import com.zsxb.crm.exception.BaseException;
import com.zsxb.crm.mapper.UserMapper;
import com.zsxb.crm.pojo.User;
import com.zsxb.crm.service.LoginService;
import com.zsxb.crm.service.UserService;
import com.zsxb.crm.utils.JwtUtils;
import com.zsxb.crm.vo.CaptchaImageVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {
    private final RedisTemplate redisTemplate;
    private final UserMapper userMapper;
    /**
     * 生成验证码图片
     *
     * 该方法用于生成一个验证码图片及其对应的验证码文本
     * 验证码图片以Base64编码的形式返回，同时生成一个唯一的键值对，用于后续验证
     * 验证码文本被存储在Redis中，与唯一键关联，以供验证时使用
     *
     * @return CaptchaImageVO对象，包含验证码图片的Base64编码字符串和唯一的键
     */
    @Override
    public CaptchaImageVO captchaImage() {
        // 创建一个规格化的验证码对象，参数分别为图片宽度、高度和验证码长度
        SpecCaptcha specCaptcha = new SpecCaptcha(85,32,3);
        // 设置验证码字符类型为默认类型
        specCaptcha.setCharType(Captcha.TYPE_DEFAULT);
        // 生成验证码文本，并转换为小写
        String code =specCaptcha.text().toLowerCase();
        // 生成一个唯一的键，用于存储验证码文本
        String key = UUID.randomUUID().toString();
        // 将验证码图片转换为Base64编码的字符串
        String image =specCaptcha.toBase64("");
        // 将验证码文本存储到Redis中，设置过期时间为LOGIN_CAPTCHA_TTL_SEC秒
        redisTemplate.opsForValue().set(key,code, RedisConstant.LOGIN_CAPTCHA_TTL_SEC, TimeUnit.SECONDS);

        // 构建并返回CaptchaImageVO对象，包含验证码图片的Base64编码字符串和唯一的键
        return CaptchaImageVO.builder()
                .img(image)
                .uuid(key)
                .build();
    }

    @Override
    public String login(LoginDTO loginDTO) {
        if (!StringUtils.hasText(loginDTO.getCode())){
            throw new BaseException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
        }
        String code = (String) redisTemplate.opsForValue().get(loginDTO.getUuid());
        if (code==null){
            throw new BaseException(ResultCodeEnum.APP_LOGIN_CODE_EXPIRED);
        }
        if (!code.equals(loginDTO.getCode().toLowerCase())){
            throw new BaseException(ResultCodeEnum.APP_LOGIN_CODE_ERROR);
        }
        User user = userMapper.findByUserName(loginDTO.getUsername());
        if (user==null){
            throw new BaseException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);
        }
        if (StatusContext.DISABLE.equals(user.getStatus())){
            throw new BaseException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);
        }
        String salt = String.valueOf(user.getSalt());
        if (!user.getPassword().equals(DigestUtils.md5Hex(loginDTO.getPassword()+salt))){
            throw new BaseException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }
        user.setLoginDate(LocalDateTime.now());
        userMapper.updateById(user);
        log.info("用户登录成功:{}",user);
        return JwtUtils.createToken(user.getUserId(),user.getUserName(),user.getLoginIp());
    }
}
